<template>
  <q-page padding>

    <q-dialog v-model="visible" persistent>
      <q-card class="full-width">
        <q-form @submit="onSubmit">
          <q-card-section>
            <div class="text-h6">{{ $t('templates') }}</div>
          </q-card-section>

          <q-card-section style="max-height: 70vh;" class="scroll">
            <div class="row q-col-gutter-x-md">
              <q-input v-model="form.name" :label="$t('name')" class="col-6" lazy-rules
              :rules="[val => val && val.length > 0 || $t('inputText')]">
                <template v-slot:append>
                  <q-select v-model="form.suffix" :options="['.java', '.vue']" />
                </template>
              </q-input>
              <q-input v-model="form.version" :label="$t('version')" class="col-3"
              :rules="[val => val && val.length > 0 || $t('inputText')]" />
              <q-input v-model="form.type" :label="$t('type')" class="col-3"
              :rules="[val => val && val.length > 0 || $t('inputText')]" />
            </div>
            <q-input v-model="form.content" :label="$t('content')" type="textarea" autogrow />
          </q-card-section>

          <q-card-actions align="right">
            <q-btn title="cancel" type="reset" unelevated :label="$t('cancel')" v-close-popup />
            <q-btn title="submit" type="submit" flat :label="$t('submit')" color="primary" />
          </q-card-actions>

        </q-form>
      </q-card>
    </q-dialog>

    <!-- preview -->
    <q-dialog v-model="previewVisible">
      <q-card style="width: 50%; max-width: 800px;">
        <q-card-section class="row items-center q-pb-none">
          <div class="text-h6">{{ $t('preview') }}</div>
          <q-space />
          <q-btn icon="sym_r_close" flat round dense v-close-popup />
        </q-card-section>

        <q-card-section style="max-height: 70vh;" class="scroll">
          <CodeRender :content="form.content" />
        </q-card-section>
      </q-card>
    </q-dialog>

    <q-table flat ref="tableRef" :title="$t('templates')" :rows="rows" :columns="columns" row-key="id"
      v-model:pagination="pagination" :loading="loading" :filter="filter" binary-state-sort @request="onRequest"
      class="full-width">
      <template v-slot:top-right>
        <q-input dense debounce="300" v-model="filter" placeholder="Search">
          <template v-slot:append>
            <q-icon name="sym_r_search" />
          </template>
        </q-input>
        <q-btn title="create" round padding="xs" class="q-mx-sm" color="primary" :disable="loading" icon="sym_r_add"
          @click="saveRow()" />
        <q-btn title="refresh" round padding="xs" flat color="primary" :disable="loading" icon="sym_r_refresh"
          @click="refresh" />
        <q-btn title="import" round padding="xs" flat color="primary" class="q-mx-sm" :disable="loading"
          icon="sym_r_database_upload" @click="importRow" />
        <q-btn title="export" round padding="xs" flat color="primary" icon="sym_r_file_export" @click="exportTable" />
      </template>

      <template v-slot:header="props">
        <q-tr :props="props">
          <q-th v-for="col in props.cols" :key="col.name" :props="props">
            {{ $t(col.label) }}
          </q-th>
        </q-tr>
      </template>

      <template v-slot:body-cell-lastModifiedDate="props">
        <q-td :props="props">
          {{ props.row.lastModifiedDate ? date.formatDate(props.row.lastModifiedDate, 'YYYY-MM-DD HH:mm') : '-' }}
        </q-td>
      </template>
      <template v-slot:body-cell-id="props">
        <q-td :props="props">
          <q-btn title="modify" padding="xs" flat round color="primary" icon="sym_r_edit" @click="saveRow(props.row.id)"
            class="q-mt-none q-mx-sm" />
          <q-btn title="preview" padding="xs" flat round color="primary" icon="sym_r_visibility"
            @click="previewRow(props.row.id)" class="q-mt-none" />
          <q-btn title="delete" padding="xs" flat round color="negative" icon="sym_r_delete"
            @click="removeRow(props.row.id)" class="q-mt-none q-ml-sm" />
        </q-td>
      </template>
    </q-table>
  </q-page>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { QTableProps } from 'quasar'
import { useQuasar, date, exportFile } from 'quasar'
import CodeRender from 'components/CodeRender.vue'
import { retrieveTemplates, fetchTemplate, createTemplate, modifyTemplate, removeTemplate } from 'src/api/templates'
import type { Template } from 'src/types'

const $q = useQuasar()

const visible = ref<boolean>(false)
const importVisible = ref<boolean>(false)
const previewVisible = ref<boolean>(false)

const tableRef = ref()
const rows = ref<QTableProps['rows']>([])
const filter = ref('')
const loading = ref<boolean>(false)

const initialValues: Template = {
  id: undefined,
  name: '',
  suffix: '',
  version: '',
  content: ''
}
const form = ref<Template>({ ...initialValues })

const pagination = ref({
  sortBy: 'id',
  descending: true,
  page: 1,
  rowsPerPage: 7,
  rowsNumber: 0
})

const columns: QTableProps['columns'] = [
  { name: 'name', label: 'name', align: 'left', field: 'name', sortable: true },
  { name: 'suffix', label: 'suffix', align: 'left', field: 'suffix' },
  { name: 'version', label: 'version', align: 'left', field: 'version' },
  { name: 'type', label: 'type', align: 'left', field: 'type' },
  { name: 'lastModifiedDate', label: 'lastModifiedDate', align: 'center', field: 'lastModifiedDate' },
  { name: 'id', label: 'actions', field: 'id' }
]

onMounted(() => {
  tableRef.value.requestServerInteraction()
})

/**
 * 查询列表
 */
async function onRequest(props: Parameters<NonNullable<QTableProps['onRequest']>>[0]) {
  loading.value = true

  const { page, rowsPerPage, sortBy, descending } = props.pagination
  const filter = props.filter

  const params = { page, size: rowsPerPage, sortBy, descending }

  retrieveTemplates({ ...params }, filter).then(res => {
    pagination.value.page = page
    pagination.value.rowsPerPage = rowsPerPage
    pagination.value.sortBy = sortBy
    pagination.value.descending = descending

    rows.value = res.data.content
    pagination.value.rowsNumber = res.data.totalElements
  }).finally(() => {
    loading.value = false
  })
}

function refresh() {
  tableRef.value.requestServerInteraction()
}

function importRow() {
  importVisible.value = true
}

function previewRow(id: number) {
  previewVisible.value = true
  loadOne(id)
}

function saveRow(id?: number) {
  form.value = { ...initialValues }
  visible.value = true
  // You can populate the form with existing user data based on the id
  if (id) {
    loadOne(id)
  }
}

async function loadOne(id: number) {
  fetchTemplate(id).then(res => { form.value = res.data })
}

function removeRow(id: number) {
  loading.value = true
  removeTemplate(id).finally(() => { loading.value = false })
}

function onSubmit() {
  if (form.value.id) {
    modifyTemplate(form.value.id, form.value)
  } else {
    createTemplate(form.value)
  }

  // Close the dialog after submitting
  visible.value = false
}


function wrapCsvValue(val: string, formatFn?: (val: string, row?: string) => string, row?: string) {
  let formatted = formatFn !== void 0 ? formatFn(val, row) : val

  formatted = formatted === void 0 || formatted === null ? '' : String(formatted)

  formatted = formatted.split('"').join('""')

  return `"${formatted}"`
}

function exportTable() {
  if (!columns || !rows.value || columns.length === 0 || rows.value.length === 0) {
    // Handle the case where columns or rows are undefined or empty
    console.error('Columns or rows are undefined or empty.')
    return
  }
  // naive encoding to csv format
  const content = [columns.map(col => wrapCsvValue(col.label))]
    .concat(rows.value.map(row => columns.map(col =>
      wrapCsvValue(typeof col.field === 'function' ? col.field(row) : row[col.field === void 0 ? col.name : col.field],
        col.format,
        row
      )).join(','))
    ).join('\r\n')

  const status = exportFile(
    'table-export.csv',
    content,
    'text/csv'
  )

  if (status !== true) {
    $q.notify({
      message: 'Browser denied file download...',
      color: 'negative',
      icon: 'warning'
    })
  }
}
</script>
